/**
 * typeof 用来返回一个变量的声明类型，如果不存在，则获取该类型的推论类型。
 * keyof 遍历某种类型的属性，并通过keyof操作符提取其属性的名称，类似Object.keys方法
 * in 用于遍历类型的属性key值，一般和keyof联合使用：
 * extends  限制范围
 * infer 可以用来声明一个待推断的类型变量，简单来说，相当于JavaScript中的const。
 */
const nb: number = 1
type TN = typeof nb

const obj = {
  name: 'zhangsan',
  age: 28,
  male: true,
  run: () => 'run'
}
type TO = typeof obj

interface Person {
  name: string;
  age: number;
  location: string;
}

type K1 = keyof Person; // "name" | "age" | "location"
const k1: K1 = 'age';
type K2 = keyof Person[];  // "length" | "push" | "pop" | "concat" | ...
const k2: K2 = "concat";
type K3 = keyof { [x: string]: Person };  // string
const k3: K3 = "2123"
const colors = {
  red: 'Red',
  green: 'Green',
  blue: 'Blue'
}
type TColors = keyof typeof colors // 'red' | 'green' | 'blue'

// Partial、Required工具函数可以用in 和keyof实现
type TempPartial<T> = {
  [key in keyof T]?: T[key]
}
type Per = TempPartial<Person>;

// 用于限制类型范围
function get<T extends object,Key extends keyof T>(obj: T,key: Key): T[Key] {
  return obj[key];
}
console.log(get(colors,'red'))
// 用于条件类型
type isNull<T> = T extends null | undefined ? true : false;
const notNullUndefined1: isNull<number> = false
const notNullUndefined2: isNull<symbol> = false
const isNullUndefined1: isNull<null> = true
const isNullUndefined2: isNull<undefined> = true

// ReturnType工具函数的推导过程可用extends
type TempReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer R ? R : any;
type T0 = TempReturnType<() => string>  // string
type T1 = TempReturnType<(s: string) => void> // void
type T2 = TempReturnType<<T>() => T>  // unkonwn

